import { Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
import { NotifyService } from '@farris/ui-notify';
import { DesignViewModelField, DesignViewModelService, DomService, FormBasicService, FormBindingType, FormComponentType, FormSchemaEntityField, FormSchemaEntityFieldTypeName } from '@farris/designer-services';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { DatagridComponent } from '@farris/ui-datagrid';
import { cloneDeep } from 'lodash-es';
import { DgControl } from '@farris/designer-services';
import { IdService } from '@farris/ui-common';
import { GSPElementDataType } from '@gsp-bef/gsp-cm-metadata';


class SaveAsTemplateEditorParam {

    /** 另存为类型：单个控件/ 容器  */
    controlCategory: 'input' | 'container';

    /** 控件名称 */
    controlTitle: string;

    /** 控件DOM结构 */
    controlDom: any;

    /** 控件所属的视图模型id */
    viewModelId?: string;

    /** 模板在工具箱中展示的图标类型 */
    templateIconType?: string;
}

class SaveAsComponentTemplateInfo {
    /** 模板id */
    id: string;
    code: string;
    /** 模板名称 */
    name: string;
    /** 模板所属表单信息、控件信息 */
    templateSource: string;

    /** 模板DOM结构 */
    templateDom: any;

    /** 模板分类 */
    templateCategory: string;

    /** 模板内需要的绑定字段 */
    bindingFields: FormSchemaEntityField[];

}

/**
 * 组件另存为编辑器
 */
@Component({
    selector: 'app-save-as-template-editor',
    templateUrl: './save-as-template-editor.component.html',
    styleUrls: ['./save-as-template-editor.component.css']
})
export class SaveAsTemplateEditorComponent implements OnInit {
    /**
     * 关闭按钮事件
     */
    @Output() closeModal = new EventEmitter<any>();
    /**
     * 确定按钮事件
     */
    @Output() submitModal = new EventEmitter<any>();
    /**
     * 表达式值
     */
    @Input() value: string;

    /**
     * 参数
     */
    @Input() editorParams: SaveAsTemplateEditorParam;

    /**
     * 绑定编辑器页尾组件
     */
    @ViewChild('bindingFooter') modalFooter: TemplateRef<any>;
    /**
     * 编辑器默认弹出窗口显示属性
     */
    public modalConfig = {
        title: '保存组件模板',
        width: 600,
        height: 500,
        showButtons: true,
        resizable: false,
        showMaxButton: false
    };

    /** 另存为类型 */
    saveAsType: 'input' | 'container';

    private templateUrl = "/api/dev/formdesigner/v1.0/field-template";

    /** 模板信息 */
    controlTemplateInfo: SaveAsComponentTemplateInfo

    /** 模板是否已保存过 */
    alreadySaved = false;

    /** 所有的子级控件 */
    allContentControls = [];

    /** 模板中勾选的子级控件 */
    selectedContentControls = [];
    @ViewChild(DatagridComponent) dataGrid: DatagridComponent;

    /** 模板id */
    templateId: string;
    /** 列表的列配置 */
    columns = [{ field: 'title', title: '控件' }];

    /** 输入控件相关的绑定字段 */
    allBindingFields = new Map<string, DesignViewModelField>();

    /** 记录容器内部绑定简单字段的控件。因为目前还不能支持复杂字段的另存为 */
    private simpleBindingControls = new Set<string>();

    /** 是否展示筛选控件的表格 */
    showFilterControlPanel = false;

    constructor(
        private domService: DomService,
        private formBasicService: FormBasicService,
        private idService: IdService,
        private http: HttpClient,
        private dgVMService: DesignViewModelService,
        private notifyService: NotifyService) { }

    ngOnInit() {
        this.saveAsType = (this.editorParams && this.editorParams.controlCategory) || 'input';

        // 获取控件DOM结构
        this.editorParams.controlDom = cloneDeep(this.editorParams.controlDom);

        this.allBindingFields.clear();

        // 获取容器内的子级输入类控件
        if (this.saveAsType === 'container') {
            this.simpleBindingControls.clear();
            this.allContentControls = this.getAllInputControls(this.editorParams.controlDom, true);
        } else {
            this.getBindingFieldForInputControl();
        }


        this.editorParams.controlDom = this.clearBindingPropertiesInControl(this.editorParams.controlDom);

        // 获取模板id
        this.getTemplateIdByFormIdAndControlId();

        // 支持Form类Component和布局容器筛选内部输入控件，不支持table类Component筛选
        this.showFilterControlPanel = this.saveAsType === 'container' && this.editorParams.controlDom.componentType !== 'table';

        // 查询模板
        this.controlTemplateInfo = new SaveAsComponentTemplateInfo();
        this.queryCurrentTemplateInfo();


    }

    private getTemplateIdByFormIdAndControlId() {
        const metadataId = this.formBasicService.formMetaBasicInfo.id;
        this.templateId = `${metadataId}_${this.editorParams.controlDom.id}`;
        this.templateId = this.idService.encrypt(this.templateId);

    }

    /**
     * 获取单个输入类控件的绑定字段
     */
    private getBindingFieldForInputControl() {
        if (this.editorParams.controlDom && this.editorParams.controlDom.binding) {
            const dgVMField = this.getBindingField(this.editorParams.controlDom.binding.field);
            this.allBindingFields.set(this.editorParams.controlDom.id, dgVMField);
        }

    }

    private getBindingField(fieldId: string) {
        const dgViewModel = this.dgVMService.getDgViewModel(this.editorParams.viewModelId);
        const dgVMField = dgViewModel.fields.find(f => f.id === fieldId);

        // 日期、数字需要明确具体类型
        switch (dgVMField.type.name) {
            case FormSchemaEntityFieldTypeName.Number: {
                dgVMField.type.elementType = dgVMField.type.length === 0 ? GSPElementDataType.Integer : GSPElementDataType.Decimal;
                break;
            }
            case FormSchemaEntityFieldTypeName.DateTime: {
                dgVMField.type.elementType = GSPElementDataType.DateTime;
                break;
            }
            case FormSchemaEntityFieldTypeName.Date: {
                dgVMField.type.elementType = GSPElementDataType.Date;
                break;
            }
        }

        return dgVMField;
    }
    /**
     * 查询当前模板信息
     */
    private queryCurrentTemplateInfo() {

        this.http.get(`${this.templateUrl}?id=${this.templateId}`).subscribe((data: Array<SaveAsComponentTemplateInfo>) => {

            if (data && data.length && data[0].templateDom) {

                // 模板已存在，可修改
                this.alreadySaved = true;
                this.controlTemplateInfo = data[0];
                this.controlTemplateInfo.templateDom = JSON.parse(data[0].templateDom);

                if (this.saveAsType === 'container' && this.controlTemplateInfo.templateDom.contents) {
                    this.selectedContentControls = this.getAllInputControls(this.controlTemplateInfo.templateDom);

                    const checkedIds = this.selectedContentControls.map(c => c.id)
                    this.dataGrid.checkRows(checkedIds);
                }
                return;
            }

            this.alreadySaved = false;
            this.controlTemplateInfo.name = this.editorParams.controlTitle;

            if (this.saveAsType === 'container') {
                this.dataGrid.checkAllRows();
            }

        })
    }
    /**
     * 查找容器内的输入控件，用于界面列表展示以及勾选
     */
    private getAllInputControls(controlDom: any, isCurrentContainer = false) {
        if (this.saveAsType !== 'container') {
            return [];
        }

        const rawControlDom = controlDom;
        if (!rawControlDom || !rawControlDom.contents || !rawControlDom.contents.length) {
            return [];
        }
        // 布局容器
        if (controlDom.type === DgControl.ResponseLayout.type) {
            return this.getAllInputControlsInResponseLayout(controlDom, isCurrentContainer);
        }
        if (controlDom.type === DgControl.Component.type) {
            // table类组件
            if (controlDom.componentType === FormComponentType.table) {
                return this.getAllInputControlsInTableComponent(controlDom, isCurrentContainer);
            }
            // form类组件
            if (controlDom.componentType && controlDom.componentType.includes(FormComponentType.form)) {
                return this.getAllInputControlsInFormComponent(controlDom, isCurrentContainer);
            }
        }

    }

    /**
     * 提取布局容器中的输入类控件
     * @param controlDom 容器DOM
     * @param isCurrentContainer 是否为当前表单的容器
     */
    private getAllInputControlsInResponseLayout(controlDom: any, isCurrentContainer = false) {
        const allContentControls = [];
        controlDom.contents.forEach(co => {
            let inputControl;
            if (co.type === DgControl.ResponseLayoutItem.type) {
                if (co.contents && co.contents.length) {
                    inputControl = co.contents[0];
                }
            }
            if (isCurrentContainer && inputControl) {
                if (inputControl && inputControl.binding && inputControl.binding.path && !inputControl.binding.path.includes('_')) {
                    this.simpleBindingControls.add(inputControl.id);
                } else {
                    this.simpleBindingControls.delete(inputControl.id);
                }
            }

            if (inputControl) {
                // 收集绑定信息
                if (isCurrentContainer) {
                    const dgVMField = this.getBindingField(inputControl.binding.field);
                    if (dgVMField) {
                        this.allBindingFields.set(inputControl.id, dgVMField);
                    }
                }

                inputControl = this.clearBindingPropertiesInControl(inputControl);
                allContentControls.push(inputControl);
            }
        })

        return allContentControls;
    }
    /**
     * 提取Form类Component内的输入类控件
     * @param controlDom 容器DOM
     * @param isCurrentContainer 是否为当前表单的容器
     */
    private getAllInputControlsInFormComponent(controlDom: any, isCurrentContainer = false) {
        const allContentControls = [];

        const formNode = this.domService.selectNode(controlDom, item => item.type === DgControl.Form.type);
        if (formNode && formNode.contents) {
            formNode.contents.forEach(inputControl => {
                if (isCurrentContainer && inputControl) {
                    if (inputControl && inputControl.binding && inputControl.binding.path && !inputControl.binding.path.includes('_')) {
                        this.simpleBindingControls.add(inputControl.id);
                    } else {
                        this.simpleBindingControls.delete(inputControl.id);
                    }
                }

                if (inputControl) {
                    // 收集绑定信息
                    if (isCurrentContainer) {
                        const dgVMField = this.getBindingField(inputControl.binding.field);
                        if (dgVMField) {
                            this.allBindingFields.set(inputControl.id, dgVMField);
                        }
                    }

                    inputControl = this.clearBindingPropertiesInControl(inputControl);
                    allContentControls.push(inputControl);
                }
            })
        }

        return allContentControls;
    }
    /**
     * 提取Table类Component中的输入类控件
     * @param controlDom 容器DOM
     * @param isCurrentContainer 是否为当前表单的容器
     */
    private getAllInputControlsInTableComponent(controlDom: any, isCurrentContainer = false) {
        const allContentControls = [];

        const tableNode = this.domService.selectNode(controlDom, item => item.type === DgControl.Table.type);
        if (tableNode && tableNode.rows) {
            tableNode.rows.forEach(row => {
                if (row.columns && row.columns.length) {
                    row.columns.forEach(column => {
                        const isEditorColumn = column.tdType === 'editor' && !column.invisible && column.editor && column.editor.type;
                        let inputControl = isEditorColumn ? column.editor : null;
                        if (isCurrentContainer && inputControl) {
                            if (inputControl && inputControl.binding && inputControl.binding.path && !inputControl.binding.path.includes('_')) {
                                this.simpleBindingControls.add(inputControl.id);
                            } else {
                                this.simpleBindingControls.delete(inputControl.id);
                            }
                        }

                        if (inputControl) {
                            // 收集绑定信息
                            if (isCurrentContainer) {
                                const dgVMField = this.getBindingField(inputControl.binding.field);
                                if (dgVMField) {
                                    this.allBindingFields.set(inputControl.id, dgVMField);
                                }
                            }

                            inputControl = this.clearBindingPropertiesInControl(inputControl);
                            allContentControls.push(inputControl);
                        }
                    })
                }
            })
        }

        return allContentControls;
    }

    /**
     *禁止行选中函数。目前只支持绑定简单字段的控件
     */
    disableRowFn = (inputControl, index) => {

        if (this.simpleBindingControls && this.simpleBindingControls.has(inputControl.id)) {
            return false;
        }
        return true;
    }
    /**
     * 清除控件中与绑定字段、变量、事件相关的属性值
     * @param inputControl 输入类控件Schema
     */
    private clearBindingPropertiesInControl(inputControl: any) {
        // 过滤binding-----这里不移除也可以，因为再次创建的时候这两个值会被覆盖掉
        // inputControl.binding = null;
        // inputControl.path = '';

        // 帮助控件
        if (inputControl.type == DgControl.LookupEdit.type) {
            inputControl.dataSource = null;
            inputControl.mapFields = '';
        }
        // 智能输入框
        if (inputControl.type == DgControl.InputGroup.type && inputControl.modalConfig && inputControl.modalConfig.modalCmp) {
            inputControl.modalConfig.modalCmp = null;
            inputControl.modalConfig.mapFields = '';
        }
        const actions = this.domService.module.actions || [];
        Object.keys(inputControl).forEach(propKey => {
            const propValue = inputControl[propKey];
            if (!propValue) {
                return;
            }
            switch (typeof (propValue)) {
                case 'object': {
                    // 绑定变量或者表达式
                    if (propValue.type === FormBindingType.Variable || propValue.type === 'Expression') {
                        inputControl[propKey] = null;
                    }

                    break;
                }
                case 'string': {
                    // 绑定状态机：增加判空条件，是为了防止目标表单里没有状态机
                    if (propValue.includes('viewModel.stateMachine') && !propValue.includes('&&')) {
                        inputControl[propKey] = `viewModel.stateMachine && ${propValue}`;
                    }

                    // 事件类属性：清空
                    const bindingAction = actions.find(action => action.sourceComponent && action.sourceComponent.id === inputControl.id);
                    if (bindingAction && bindingAction.map) {
                        const eventBinding = bindingAction.map.find(item => item.event && item.event.label === propKey);
                        if (eventBinding) {
                            inputControl[propKey] = null;
                        }
                    }
                }

            }


        })
        return inputControl;
    }

    clickCancel() {
        this.closeModal.emit();
    }

    clickConfirm() {
        if (this.saveAsType === 'input') {
            this.saveSingleControlAsTemplate();

        } else {
            this.saveContainerAsTemplate();
        }

    }

    /**
     * 单个输入控件
     */
    private saveSingleControlAsTemplate() {

        const templateDom = cloneDeep(this.editorParams.controlDom);
        const bindingField = this.allBindingFields.get(templateDom.id);
        if (bindingField) {
            this.saveTemplate(templateDom, [bindingField]);
        }
    }

    /**
     * 容器类控件
     */
    private saveContainerAsTemplate() {
        const checkeds = this.dataGrid.checkedRows;
        const checkedControlIds = checkeds.map(c => c.data.id);
        if (!checkedControlIds.length) {
            this.notifyService.warning('请先选择控件！');
            return;
        }


        const templateDom = this.assembleTemplateDomByChecked();


        // 过滤绑定字段
        const selectedBindingFields = [];
        checkedControlIds.forEach(controlId => {
            const bindingField = this.allBindingFields.get(controlId);
            selectedBindingFields.push(bindingField);
        })

        this.saveTemplate(templateDom, selectedBindingFields);
    }


    /**
     * 根据勾选的控件，筛选容器的子级控件
     */
    private assembleTemplateDomByChecked() {

        const controlDom = this.editorParams.controlDom;
        let templateDomAfterChecked;
        // 布局容器
        if (controlDom.type === DgControl.ResponseLayout.type) {
            templateDomAfterChecked = this.assembleTemplateDomByCheckedInResponseLayout();
        }
        if (controlDom.type === DgControl.Component.type) {
            // table类组件
            if (controlDom.componentType === FormComponentType.table) {
                templateDomAfterChecked = this.assembleTemplateDomByCheckedInTableComponent();
            }
            // form类组件
            if (controlDom.componentType && controlDom.componentType.includes(FormComponentType.form)) {
                templateDomAfterChecked = this.assembleTemplateDomByCheckedInFormComponent();
            }
        }

        return templateDomAfterChecked;
    }


    private assembleTemplateDomByCheckedInResponseLayout() {
        const checkeds = this.dataGrid.checkedRows;
        const checkedControlIds = checkeds.map(c => c.data.id);

        const rawControlDom = cloneDeep(this.editorParams.controlDom);

        // 未勾选的字段所在的布局项，contents节点置为[]
        rawControlDom.contents.forEach((co, index) => {
            if (co.contents && co.contents.length && !checkedControlIds.includes(co.contents[0].id)) {
                co.contents.length = 0;
            }
        })
        return rawControlDom;

    }

    /**
     * 表格类组件，组装筛选后的DOM结构
     */
    private assembleTemplateDomByCheckedInTableComponent() {
        const checkeds = this.dataGrid.checkedRows;
        const checkedControlIds = checkeds.map(c => c.data.id);

        const rawControlDom = cloneDeep(this.editorParams.controlDom);
        const tableNode = this.domService.selectNode(rawControlDom, item => item.type === DgControl.Table.type);


        // 为勾选的单元格：清除编辑器单元格的绑定信息和前置静态文本单元格的标题
        tableNode.rows.forEach(row => {
            if (row.columns && row.columns.length) {
                row.columns.forEach((column, index) => {
                    const isEditorColumn = column.tdType === 'editor' && !column.invisible && column.editor;
                    let inputControl = isEditorColumn ? column.editor : null;

                    if (inputControl && !checkedControlIds.includes(inputControl.id)) {
                        column.editor = {
                            binding: null,
                            type: null
                        };
                        column.staticText = {
                            text: '',
                            require: false
                        };

                        const staticTextColumn = row.columns[index - 1];
                        staticTextColumn.staticText = {
                            text: '',
                            require: false
                        };
                    }
                })
            }
        })

        return rawControlDom;

    }

    /**
     * Form类组件，组装筛选后的DOM结构
     */
    private assembleTemplateDomByCheckedInFormComponent() {
        const checkeds = this.dataGrid.checkedRows;
        const checkedControlIds = checkeds.map(c => c.data.id);

        const rawControlDom = cloneDeep(this.editorParams.controlDom);
        const formNode = this.domService.selectNode(rawControlDom, item => item.type === DgControl.Form.type);

        // 清除未勾选的控件
        formNode.contents.forEach(inputControl => {
            if (!checkedControlIds.includes(inputControl.id)) {
                inputControl.unSelectedInTemplate = true;
            }
        })

        formNode.contents = formNode.contents.filter(co => !co.unSelectedInTemplate);

        return rawControlDom;
    }

    private saveTemplate(templateDom: any, bindingFields: FormSchemaEntityField[]) {
        if (!this.controlTemplateInfo.name) {
            this.notifyService.warning('请填写模板名称！');
            return;
        }
        const headerOption = {
            headers: new HttpHeaders({ 'Content-Type': 'application/json' })
        }

        let templateIconType = this.editorParams.templateIconType || this.editorParams.controlDom.type;


        const body = {
            id: this.templateId,
            code: this.templateId,
            name: this.controlTemplateInfo.name,
            templateCategory: this.editorParams.controlCategory,
            templateSource: JSON.stringify({
                formId: this.formBasicService.formMetaBasicInfo.id,
                formName: this.formBasicService.formMetaBasicInfo.name,
                controlId: this.editorParams.controlDom.id,
                templateIconType
            }),
            templateDom: JSON.stringify(templateDom),
            bindingFields: JSON.stringify(bindingFields)
        }
        return this.http.post(this.templateUrl, body, headerOption).subscribe((data: any) => {
            if (data && data.state) {
                const msg = this.alreadySaved ? '更新模板成功' : '保存模板成功';
                this.notifyService.success(msg);
                this.submitModal.emit();
            }
            if (data && !data.state) {
                this.notifyService.warning(data.errorMessage || '保存模板失败');
            }
        }, () => {
            this.notifyService.warning('保存模板失败');
        });
    }
}
